/*
A simple music player.
*/

#include <string.h>

#include <nes.h>

// include NESLIB header
#include "../neslib/neslib.h"

#include "apu.h"

//
// MUSIC ROUTINES
//

// Namespace(bias=1.0, freq=111860.8, length=64, maxbits=13.0, upper=41)
// 439.0 0.943191918851 41
const int note_table_41[64] = {
    4318,
    4076,
    3847,
    3631,
    3427,
    3235,
    3053,
    2882,
    2720,
    2567,
    2423,
    2287,
    2159,
    2037,
    1923,
    1815,
    1713,
    1617,
    1526,
    1440,
    1360,
    1283,
    1211,
    1143,
    1079,
    1018,
    961,
    907,
    856,
    808,
    763,
    720,
    679,
    641,
    605,
    571,
    539,
    509,
    480,
    453,
    428,
    403,
    381,
    359,
    339,
    320,
    302,
    285,
    269,
    254,
    240,
    226,
    213,
    201,
    190,
    179,
    169,
    160,
    151,
    142,
    134,
    126,
    119,
    113,
};

// Namespace(bias=1.0, freq=111860.8, length=64, maxbits=13, upper=49)
// 440.5 1.79281159771 49
const int note_table_49[64] = {
    4304,
    4062,
    3834,
    3619,
    3416,
    3224,
    3043,
    2872,
    2711,
    2559,
    2415,
    2279,
    2151,
    2031,
    1917,
    1809,
    1707,
    1611,
    1521,
    1436,
    1355,
    1279,
    1207,
    1139,
    1075,
    1015,
    958,
    904,
    853,
    805,
    760,
    717,
    677,
    639,
    603,
    569,
    537,
    507,
    478,
    451,
    426,
    402,
    379,
    358,
    338,
    319,
    301,
    284,
    268,
    253,
    239,
    225,
    213,
    201,
    189,
    179,
    168,
    159,
    150,
    142,
    134,
    126,
    119,
    112,
};

// Namespace(bias=1.0, freq=111860.8, length=64, maxbits=12, upper=63)
// 443.6 14.2328382554 63
const int note_table_63[64] = {
    2137,
    4034,
    3807,
    3593,
    3392,
    3201,
    3022,
    2852,
    2692,
    2541,
    2398,
    2263,
    2136,
    2016,
    1903,
    1796,
    1695,
    1600,
    1510,
    1425,
    1345,
    1270,
    1199,
    1131,
    1068,
    1008,
    951,
    898,
    847,
    800,
    755,
    712,
    672,
    634,
    599,
    565,
    533,
    503,
    475,
    448,
    423,
    399,
    377,
    356,
    336,
    317,
    299,
    282,
    266,
    251,
    237,
    224,
    211,
    199,
    188,
    177,
    167,
    158,
    149,
    141,
    133,
    125,
    118,
    111,
};

// Namespace(bias=-1.0, freq=55930.4, length=64, maxbits=12, upper=53)
// 443.7 8.47550713772 53
const int note_table_tri[64] = {
    2138,
    2018,
    1905,
    1798,
    1697,
    1602,
    1512,
    1427,
    1347,
    1272,
    1200,
    1133,
    1069,
    1009,
    953,
    899,
    849,
    801,
    756,
    714,
    674,
    636,
    601,
    567,
    535,
    505,
    477,
    450,
    425,
    401,
    379,
    358,
    338,
    319,
    301,
    284,
    268,
    253,
    239,
    226,
    213,
    201,
    190,
    179,
    169,
    160,
    151,
    142,
    135,
    127,
    120,
    113,
    107,
    101,
    95,
    90,
    85,
    80,
    76,
    72,
    68,
    64,
    60,
    57,
};

#define NOTE_TABLE note_table_49
#define BASS_NOTE 36

byte music_index = 0;
byte cur_duration = 0;

const byte music1[]; // music data -- see end of file
const byte *music_ptr = music1;

byte next_music_byte()
{
  return *music_ptr++;
}

void play_music()
{
  static byte chs = 0;
  if (music_ptr)
  {
    // run out duration timer yet?
    while (cur_duration == 0)
    {
      // fetch next byte in score
      byte note = next_music_byte();
      // is this a note?
      if ((note & 0x80) == 0)
      {
        // pulse plays higher notes, triangle for lower if it's free
        if (note >= BASS_NOTE || (chs & 4))
        {
          int period = NOTE_TABLE[note & 63];
          // see which pulse generator is free
          if (!(chs & 1))
          {
            APU_PULSE_DECAY(0, period, DUTY_25, 2, 10);
            chs |= 1;
          }
          else if (!(chs & 2))
          {
            APU_PULSE_DECAY(1, period, DUTY_25, 2, 10);
            chs |= 2;
          }
        }
        else
        {
          int period = note_table_tri[note & 63];
          APU_TRIANGLE_LENGTH(period, 15);
          chs |= 4;
        }
      }
      else
      {
        // end of score marker
        if (note == 0xff)
          music_ptr = NULL;
        // set duration until next note
        cur_duration = note & 63;
        // reset channel used mask
        chs = 0;
      }
    }
    cur_duration--;
  }
}

void start_music(const byte *music)
{
  music_ptr = music;
  cur_duration = 0;
}

void main(void)
{
  apu_init();
  music_ptr = 0;
  while (1)
  {
    if (!music_ptr)
      start_music(music1);
    waitvsync();
    play_music();
  }
}

//
// MUSIC DATA -- "The Easy Winners" by Scott Jopline
//
const byte music1[] = {
    0x2a, 0x1e, 0x95, 0x33, 0x27, 0x9f, 0x31, 0x25, 0x8a, 0x2f, 0x23, 0x8b, 0x2e, 0x22, 0x89, 0x2c, 0x20, 0x8b, 0x2a, 0x1e, 0x95, 0x28, 0x1c, 0x8a, 0x27, 0x1b, 0x95, 0x25, 0x19, 0x8b, 0x23, 0x17, 0x89, 0x22, 0x12, 0x8b, 0x23, 0x8a, 0x25, 0x8b, 0x27, 0x89, 0x28, 0x1e, 0x8c, 0x2a, 0x1c, 0x89, 0x2c, 0x1b, 0x8c, 0x2e, 0x19, 0x89, 0x2f, 0x17, 0x95, 0x27, 0x23, 0x1e, 0x95, 0x12, 0x95, 0x23, 0x1e, 0x27, 0x95, 0x2f, 0x33, 0x17, 0x95, 0x2f, 0x33, 0x27, 0x94, 0x12, 0x95, 0x33, 0x36, 0x23, 0x95, 0x38, 0x32, 0x17, 0x8b, 0x33, 0x36, 0x89, 0x1e, 0x27, 0x23, 0x8b, 0x38, 0x32, 0x8a, 0x33, 0x36, 0x12, 0x8b, 0x32, 0x38, 0x89, 0x36, 0x33, 0x27, 0x95, 0x3d, 0x37, 0x10, 0x8b, 0x3b, 0x38, 0x8a, 0x20, 0x23, 0x28, 0x8b, 0x37, 0x3d, 0x89, 0x38, 0x3b, 0x10, 0x8b, 0x37, 0x3d, 0x8a, 0x3b, 0x38, 0x28, 0x8b, 0x36, 0x33, 0x8a, 0x17, 0x95, 0x2a, 0x1e, 0x23, 0x8b, 0x2c, 0x89, 0x2e, 0x12, 0x8b, 0x2f, 0x8a, 0x31, 0x27, 0x23, 0x8b, 0x32, 0x89, 0x2f, 0x33, 0x17, 0x95, 0x33, 0x2f, 0x1e, 0x95, 0x12, 0x94, 0x36, 0x33, 0x1e, 0x95, 0x32, 0x38, 0x17, 0x8b, 0x36, 0x33, 0x89, 0x23, 0x1e, 0x27, 0x8b, 0x38, 0x32, 0x8a, 0x33, 0x36, 0x18, 0x8b, 0x33, 0x36, 0x8a, 0x33, 0x36, 0x2a, 0x95, 0x36, 0x19, 0x8b, 0x31, 0x2e, 0x89, 0x25, 0x22, 0x2a, 0x8b, 0x36, 0x8a, 0x2f, 0x35, 0x19, 0x8b, 0x36, 0x89, 0x38, 0x2f, 0x29, 0x95, 0x2e, 0x36, 0x1e, 0x95, 0x1c, 0x28, 0x95, 0x27, 0x1b, 0x8b, 0x2a, 0x8a, 0x2e, 0x25, 0x19, 0x8b, 0x34, 0x89, 0x33, 0x2f, 0x23, 0x95, 0x33, 0x2f, 0x1e, 0x95, 0x12, 0x94, 0x33, 0x36, 0x23, 0x95, 0x32, 0x38, 0x17, 0x8b, 0x33, 0x36, 0x8a, 0x23, 0x27, 0x1e, 0x8b, 0x38, 0x32, 0x89, 0x36, 0x33, 0x12, 0x8b, 0x32, 0x38, 0x8a, 0x33, 0x36, 0x1e, 0x94, 0x37, 0x3d, 0x10, 0x8b, 0x3b, 0x38, 0x8a, 0x23, 0x28, 0x20, 0x8b, 0x3d, 0x37, 0x89, 0x3b, 0x38, 0x1c, 0x8b, 0x38, 0x3b, 0x8a, 0x3a, 0x3d, 0x38, 0x8b, 0x3f, 0x37, 0x3a, 0x89, 0x27, 0x1b, 0x8b, 0x33, 0x8a, 0x37, 0x22, 0x16, 0x8b, 0x3a, 0x8a, 0x3f, 0x0f, 0x1b, 0x95, 0x3a, 0x8b, 0x3b, 0x8a, 0x3d, 0x37, 0x1c, 0x8b, 0x3b, 0x38, 0x89, 0x23, 0x28, 0x20, 0x8b, 0x3d, 0x37, 0x8a, 0x38, 0x3b, 0x10, 0x8b, 0x3d, 0x37, 0x89, 0x38, 0x3b, 0x20, 0x8b, 0x36, 0x33, 0x8a, 0x17, 0x23, 0x8b, 0x38, 0x34, 0x8a, 0x33, 0x36, 0x1e, 0x8b, 0x31, 0x34, 0x8a, 0x2f, 0x33, 0x17, 0x8b, 0x36, 0x33, 0x8a, 0x23, 0x27, 0x1e, 0x8b, 0x33, 0x36, 0x8a, 0x36, 0x30, 0x12, 0x8a, 0x34, 0x31, 0x8a, 0x1e, 0x28, 0x22, 0x8b, 0x30, 0x36, 0x89, 0x34, 0x31, 0x12, 0x8b, 0x2e, 0x28, 0x33, 0x8a, 0x31, 0x28, 0x2e, 0x95, 0x27, 0x2f, 0x1e, 0x95, 0x12, 0x95, 0x14, 0x94, 0x16, 0x95, 0x2f, 0x33, 0x17, 0x95, 0x2f, 0x33, 0x27, 0x94, 0x12, 0x95, 0x36, 0x33, 0x23, 0x95, 0x32, 0x38, 0x17, 0x8a, 0x33, 0x36, 0x8a, 0x23, 0x27, 0x1e, 0x8b, 0x32, 0x38, 0x8a, 0x33, 0x36, 0x12, 0x8b, 0x38, 0x32, 0x8a, 0x36, 0x33, 0x27, 0x95, 0x3d, 0x37, 0x10, 0x8a, 0x3b, 0x38, 0x8a, 0x23, 0x28, 0x20, 0x8b, 0x37, 0x3d, 0x89, 0x3b, 0x38, 0x10, 0x8b, 0x37, 0x3d, 0x8a, 0x38, 0x3b, 0x23, 0x8b, 0x36, 0x33, 0x8a, 0x17, 0x95, 0x2a, 0x1e, 0x23, 0x8b, 0x2c, 0x8a, 0x2e, 0x12, 0x8b, 0x2f, 0x89, 0x31, 0x23, 0x1e, 0x8b, 0x32, 0x8a, 0x33, 0x2f, 0x17, 0x95, 0x2f, 0x33, 0x1e, 0x94, 0x12, 0x95, 0x36, 0x33, 0x27, 0x95, 0x38, 0x32, 0x17, 0x8a, 0x36, 0x33, 0x8a, 0x23, 0x1e, 0x27, 0x8b, 0x38, 0x32, 0x89, 0x33, 0x36, 0x18, 0x8c, 0x36, 0x33, 0x89, 0x33, 0x36, 0x21, 0x95, 0x36, 0x19, 0x8b, 0x2e, 0x31, 0x8a, 0x25, 0x2a, 0x22, 0x8b, 0x36, 0x89, 0x35, 0x2f, 0x19, 0x8b, 0x36, 0x8a, 0x2f, 0x38, 0x25, 0x94, 0x36, 0x2e, 0x2a, 0x95, 0x1c, 0x28, 0x95, 0x27, 0x1b, 0x8c, 0x2a, 0x89, 0x2e, 0x25, 0x19, 0x8b, 0x34, 0x8a, 0x33, 0x2f, 0x23, 0x95, 0x2f, 0x33, 0x1e, 0x94, 0x12, 0x95, 0x33, 0x36, 0x23, 0x95, 0x32, 0x38, 0x17, 0x8a, 0x33, 0x36, 0x8a, 0x23, 0x1e, 0x27, 0x8b, 0x32, 0x38, 0x89, 0x36, 0x33, 0x12, 0x8c, 0x32, 0x38, 0x89, 0x33, 0x36, 0x1e, 0x95, 0x37, 0x3d, 0x10, 0x8b, 0x3b, 0x38, 0x8a, 0x23, 0x20, 0x28, 0x8a, 0x3d, 0x37, 0x8a, 0x38, 0x3b, 0x1c, 0x8b, 0x3b, 0x38, 0x8a, 0x3d, 0x38, 0x3a, 0x8b, 0x3a, 0x3f, 0x37, 0x89, 0x27, 0x1b, 0x8b, 0x33, 0x8a, 0x37, 0x22, 0x16, 0x8b, 0x3a, 0x8a, 0x3f, 0x0f, 0x1b, 0x95, 0x3a, 0x8b, 0x3b, 0x8a, 0x3d, 0x37, 0x1c, 0x8b, 0x3b, 0x38, 0x8a, 0x20, 0x28, 0x23, 0x8b, 0x3d, 0x37, 0x89, 0x38, 0x3b, 0x10, 0x8b, 0x3d, 0x37, 0x8a, 0x38, 0x3b, 0x20, 0x8b, 0x33, 0x36, 0x89, 0x17, 0x23, 0x8b, 0x38, 0x34, 0x8a, 0x36, 0x33, 0x23, 0x8b, 0x34, 0x31, 0x89, 0x2f, 0x33, 0x17, 0x8c, 0x36, 0x33, 0x89, 0x1e, 0x27, 0x23, 0x8c, 0x33, 0x36, 0x89, 0x36, 0x30, 0x12, 0x8b, 0x34, 0x31, 0x8a, 0x1e, 0x28, 0x22, 0x8a, 0x30, 0x36, 0x8a, 0x34, 0x31, 0x1e, 0x8b, 0x28, 0x2e, 0x33, 0x89, 0x28, 0x31, 0x2e, 0x95, 0x27, 0x2f, 0x17, 0x95, 0x12, 0x1e, 0x95, 0x3b, 0x36, 0x33, 0x96, 0x2a, 0x8b, 0x2b, 0x8a, 0x2c, 0x1e, 0x12, 0x8b, 0x2d, 0x89, 0x2e, 0x28, 0x1e, 0x8b, 0x2e, 0x31, 0x8a, 0x16, 0x22, 0x8b, 0x36, 0x89, 0x34, 0x1e, 0x22, 0x8b, 0x31, 0x8a, 0x2c, 0x25, 0x19, 0x8b, 0x2d, 0x89, 0x2e, 0x28, 0x25, 0x8b, 0x33, 0x2e, 0x8a, 0x25, 0x19, 0x8c, 0x31, 0x89, 0x2c, 0x1a, 0x26, 0x8b, 0x2e, 0x8a, 0x2f, 0x1b, 0x27, 0x8b, 0x2a, 0x89, 0x2c, 0x23, 0x1e, 0x8b, 0x2e, 0x8a, 0x2f, 0x12, 0x1e, 0x8b, 0x30, 0x89, 0x31, 0x27, 0x23, 0x8b, 0x32, 0x8a, 0x33, 0x17, 0x23, 0x8b, 0x32, 0x8a, 0x33, 0x1e, 0x23, 0x8b, 0x38, 0x33, 0x8a, 0x1e, 0x12, 0x8b, 0x36, 0x8a, 0x31, 0x1e, 0x23, 0x8b, 0x33, 0x89, 0x34, 0x25, 0x19, 0x8b, 0x3d, 0x89, 0x1e, 0x28, 0x22, 0x8b, 0x33, 0x89, 0x34, 0x12, 0x1e, 0x8b, 0x3d, 0x8a, 0x1e, 0x22, 0x28, 0x8a, 0x33, 0x8a, 0x34, 0x19, 0x25, 0x8b, 0x3d, 0x89, 0x28, 0x1e, 0x22, 0x8b, 0x3b, 0x89, 0x3a, 0x1e, 0x12, 0x8b, 0x38, 0x8a, 0x36, 0x22, 0x16, 0x8b, 0x34, 0x8a, 0x33, 0x23, 0x17, 0x8b, 0x3b, 0x8a, 0x1e, 0x23, 0x27, 0x8a, 0x32, 0x8a, 0x33, 0x12, 0x1e, 0x8b, 0x3b, 0x89, 0x27, 0x23, 0x1e, 0x8b, 0x32, 0x89, 0x33, 0x23, 0x17, 0x8b, 0x3b, 0x89, 0x1e, 0x23, 0x27, 0x8b, 0x38, 0x8a, 0x36, 0x12, 0x1e, 0x8b, 0x33, 0x89, 0x31, 0x1e, 0x27, 0x8b, 0x2f, 0x8a, 0x2e, 0x20, 0x14, 0x8b, 0x2f, 0x8a, 0x30, 0x2a, 0x24, 0x8b, 0x30, 0x38, 0x8a, 0x24, 0x18, 0x8b, 0x36, 0x89, 0x33, 0x24, 0x20, 0x8b, 0x30, 0x8a, 0x2e, 0x27, 0x1b, 0x8b, 0x2f, 0x89, 0x30, 0x24, 0x2a, 0x8b, 0x30, 0x38, 0x8a, 0x20, 0x14, 0x8b, 0x33, 0x36, 0x8a, 0x38, 0x30, 0x24, 0x8b, 0x33, 0x36, 0x89, 0x34, 0x31, 0x19, 0x8b, 0x30, 0x33, 0x89, 0x31, 0x34, 0x25, 0x8b, 0x2c, 0x89, 0x1c, 0x8b, 0x30, 0x8a, 0x31, 0x20, 0x28, 0x8a, 0x34, 0x8a, 0x38, 0x19, 0x8b, 0x33, 0x89, 0x34, 0x25, 0x20, 0x8b, 0x31, 0x8a, 0x25, 0x20, 0x1c, 0x8b, 0x2c, 0x8a, 0x28, 0x8b, 0x25, 0x8a, 0x26, 0x1d, 0x8a, 0x29, 0x20, 0x8a, 0x2c, 0x23, 0x8b, 0x2f, 0x26, 0x89, 0x32, 0x29, 0x8b, 0x32, 0x29, 0x94, 0x32, 0x29, 0x94, 0x35, 0x2c, 0x8a, 0x38, 0x2f, 0x8a, 0x3b, 0x32, 0x8a, 0x35, 0x3e, 0xa8, 0x2f, 0x3f, 0x36, 0x8b, 0x3b, 0x8a, 0x36, 0x8b, 0x33, 0x94, 0x2f, 0x8a, 0x27, 0x8b, 0x2a, 0x89, 0x2a, 0x2e, 0x28, 0x8b, 0x31, 0x2a, 0x2e, 0x8a, 0x1e, 0x12, 0x8b, 0x2f, 0x2a, 0x27, 0x8a, 0x17, 0x23, 0x95, 0x2a, 0x8b, 0x2b, 0x8a, 0x2c, 0x1e, 0x12, 0x8a, 0x2d, 0x8a, 0x2e, 0x25, 0x1e, 0x8b, 0x31, 0x2e, 0x89, 0x22, 0x16, 0x8b, 0x36, 0x8a, 0x34, 0x1e, 0x22, 0x8a, 0x31, 0x8a, 0x2c, 0x25, 0x19, 0x8b, 0x2d, 0x89, 0x2e, 0x28, 0x25, 0x8b, 0x33, 0x2e, 0x8a, 0x19, 0x25, 0x8a, 0x31, 0x8a, 0x2c, 0x1a, 0x26, 0x8b, 0x2e, 0x89, 0x2f, 0x27, 0x1b, 0x8b, 0x2a, 0x89, 0x2c, 0x23, 0x1e, 0x8b, 0x2e, 0x8a, 0x2f, 0x1e, 0x12, 0x8b, 0x30, 0x89, 0x31, 0x27, 0x23, 0x8b, 0x32, 0x8a, 0x33, 0x17, 0x23, 0x8b, 0x32, 0x8a, 0x33, 0x1e, 0x23, 0x8b, 0x33, 0x38, 0x8a, 0x12, 0x1e, 0x8b, 0x36, 0x8a, 0x31, 0x27, 0x1e, 0x8b, 0x33, 0x89, 0x34, 0x25, 0x19, 0x8b, 0x3d, 0x89, 0x28, 0x1e, 0x22, 0x8b, 0x33, 0x8a, 0x34, 0x1e, 0x12, 0x8b, 0x3d, 0x89, 0x1e, 0x22, 0x28, 0x8b, 0x33, 0x89, 0x34, 0x19, 0x25, 0x8b, 0x3d, 0x8a, 0x22, 0x1e, 0x28, 0x8b, 0x3b, 0x89, 0x3a, 0x12, 0x1e, 0x8b, 0x38, 0x89, 0x36, 0x22, 0x16, 0x8b, 0x34, 0x8a, 0x33, 0x23, 0x17, 0x8b, 0x3b, 0x8a, 0x1e, 0x27, 0x23, 0x8b, 0x32, 0x8a, 0x33, 0x1e, 0x12, 0x8a, 0x3b, 0x8a, 0x23, 0x1e, 0x27, 0x8b, 0x32, 0x89, 0x33, 0x23, 0x17, 0x8b, 0x3b, 0x8a, 0x27, 0x1e, 0x23, 0x8a, 0x38, 0x8a, 0x36, 0x12, 0x1e, 0x8b, 0x33, 0x8a, 0x31, 0x1e, 0x23, 0x8b, 0x2f, 0x89, 0x2e, 0x14, 0x20, 0x8b, 0x2f, 0x8a, 0x30, 0x24, 0x20, 0x8b, 0x38, 0x30, 0x89, 0x18, 0x24, 0x8c, 0x36, 0x8a, 0x33, 0x24, 0x20, 0x8a, 0x30, 0x8a, 0x2e, 0x27, 0x1b, 0x8b, 0x2f, 0x89, 0x30, 0x24, 0x20, 0x8b, 0x38, 0x30, 0x8a, 0x14, 0x20, 0x8b, 0x36, 0x33, 0x8a, 0x30, 0x38, 0x20, 0x8b, 0x36, 0x33, 0x8a, 0x31, 0x34, 0x19, 0x8b, 0x33, 0x30, 0x89, 0x34, 0x31, 0x25, 0x8b, 0x2c, 0x8a, 0x1c, 0x8a, 0x30, 0x8a, 0x31, 0x28, 0x20, 0x8b, 0x34, 0x89, 0x38, 0x19, 0x8b, 0x33, 0x8a, 0x34, 0x25, 0x20, 0x8b, 0x31, 0x8a, 0x25, 0x20, 0x1c, 0x8b, 0x2c, 0x89, 0x28, 0x8b, 0x25, 0x8a, 0x26, 0x1d, 0x8b, 0x29, 0x20, 0x89, 0x2c, 0x23, 0x8b, 0x2f, 0x26, 0x8a, 0x32, 0x29, 0x8a, 0x32, 0x29, 0x95, 0x32, 0x29, 0x94, 0x35, 0x2c, 0x8a, 0x38, 0x2f, 0x8b, 0x3b, 0x32, 0x89, 0x3e, 0x35, 0xa9, 0x36, 0x3f, 0x2f, 0x8b, 0x3b, 0x8a, 0x36, 0x8b, 0x33, 0x95, 0x2f, 0x89, 0x27, 0x8b, 0x2a, 0x89, 0x28, 0x31, 0x2a, 0x8b, 0x2e, 0x31, 0x28, 0x8a, 0x12, 0x1e, 0x8b, 0x27, 0x2a, 0x2f, 0x8a, 0x17, 0x23, 0x95, 0x2a, 0x94, 0x33, 0x2f, 0x17, 0x94, 0x2f, 0x33, 0x1e, 0x95, 0x12, 0x94, 0x33, 0x36, 0x23, 0x95, 0x38, 0x32, 0x17, 0x8a, 0x33, 0x36, 0x8a, 0x27, 0x1e, 0x23, 0x8b, 0x32, 0x38, 0x8a, 0x33, 0x36, 0x12, 0x8b, 0x32, 0x38, 0x89, 0x33, 0x36, 0x27, 0x95, 0x3d, 0x37, 0x10, 0x8b, 0x38, 0x3b, 0x8a, 0x28, 0x20, 0x23, 0x8b, 0x3d, 0x37, 0x89, 0x3b, 0x38, 0x10, 0x8b, 0x3d, 0x37, 0x8a, 0x38, 0x3b, 0x23, 0x8b, 0x36, 0x33, 0x8a, 0x17, 0x95, 0x2a, 0x1e, 0x23, 0x8b, 0x2c, 0x89, 0x2e, 0x12, 0x8b, 0x2f, 0x8a, 0x31, 0x23, 0x1e, 0x8b, 0x32, 0x89, 0x33, 0x2f, 0x17, 0x94, 0x2f, 0x33, 0x1e, 0x95, 0x12, 0x94, 0x33, 0x36, 0x27, 0x95, 0x38, 0x32, 0x17, 0x8b, 0x36, 0x33, 0x8a, 0x23, 0x27, 0x1e, 0x8b, 0x32, 0x38, 0x8a, 0x33, 0x36, 0x18, 0x8b, 0x36, 0x33, 0x8a, 0x33, 0x36, 0x2a, 0x95, 0x36, 0x19, 0x8b, 0x31, 0x2e, 0x89, 0x22, 0x2a, 0x25, 0x8b, 0x36, 0x89, 0x35, 0x2f, 0x19, 0x8b, 0x36, 0x8a, 0x2f, 0x38, 0x25, 0x95, 0x2e, 0x36, 0x2a, 0x95, 0x28, 0x1c, 0x95, 0x27, 0x1b, 0x8b, 0x2a, 0x8a, 0x2e, 0x25, 0x19, 0x8b, 0x34, 0x89, 0x33, 0x2f, 0x17, 0x95, 0x2f, 0x33, 0x23, 0x94, 0x12, 0x95, 0x33, 0x36, 0x1e, 0x95, 0x38, 0x32, 0x17, 0x8b, 0x36, 0x33, 0x8a, 0x23, 0x27, 0x1e, 0x8b, 0x32, 0x38, 0x8a, 0x33, 0x36, 0x12, 0x8b, 0x38, 0x32, 0x8a, 0x33, 0x36, 0x1e, 0x95, 0x3d, 0x37, 0x10, 0x8b, 0x3b, 0x38, 0x89, 0x23, 0x28, 0x20, 0x8b, 0x37, 0x3d, 0x8a, 0x38, 0x3b, 0x1c, 0x8b, 0x38, 0x3b, 0x89, 0x38, 0x3d, 0x3a, 0x8b, 0x3f, 0x3a, 0x37, 0x8a, 0x1b, 0x27, 0x8b, 0x33, 0x8a, 0x37, 0x22, 0x16, 0x8b, 0x3a, 0x8a, 0x3f, 0x0f, 0x1b, 0x95, 0x3a, 0x8b, 0x3b, 0x89, 0x3d, 0x37, 0x1c, 0x8b, 0x38, 0x3b, 0x8a, 0x28, 0x20, 0x23, 0x8a, 0x3d, 0x37, 0x8a, 0x38, 0x3b, 0x10, 0x8b, 0x3d, 0x37, 0x89, 0x3b, 0x38, 0x20, 0x8b, 0x33, 0x36, 0x8a, 0x23, 0x17, 0x8b, 0x38, 0x34, 0x8a, 0x33, 0x36, 0x27, 0x8b, 0x34, 0x31, 0x8a, 0x33, 0x2f, 0x23, 0x8b, 0x36, 0x33, 0x8a, 0x1e, 0x23, 0x27, 0x8b, 0x33, 0x36, 0x8a, 0x36, 0x30, 0x12, 0x8b, 0x34, 0x31, 0x89, 0x1e, 0x28, 0x22, 0x8b, 0x30, 0x36, 0x89, 0x31, 0x34, 0x1e, 0x8b, 0x2e, 0x28, 0x33, 0x8a, 0x28, 0x31, 0x2e, 0x95, 0x2f, 0x27, 0x17, 0x95, 0x12, 0x1e, 0x95, 0x36, 0x33, 0x3b, 0xa9, 0x34, 0x28, 0x95, 0x34, 0x28, 0xa0, 0x2f, 0x23, 0x8a, 0x34, 0x28, 0x8b, 0x36, 0x2a, 0x8a, 0x38, 0x2c, 0x94, 0x2c, 0x38, 0xa1, 0x2f, 0x23, 0x89, 0x28, 0x34, 0x8b, 0x2c, 0x38, 0x8a, 0x39, 0x3b, 0x2f, 0x8b, 0x3f, 0x39, 0x36, 0x94, 0x33, 0x39, 0x3d, 0x8a, 0x17, 0x23, 0x8b, 0x3b, 0x33, 0x39, 0x89, 0x33, 0x2f, 0x2d, 0x95, 0x34, 0x2c, 0x2f, 0x95, 0x1c, 0x10, 0x95, 0x12, 0x1e, 0x95, 0x2f, 0x14, 0x20, 0x8b, 0x30, 0x89, 0x31, 0x21, 0x15, 0x8b, 0x39, 0x8a, 0x28, 0x2d, 0x25, 0x8b, 0x36, 0x8a, 0x30, 0x1e, 0x2a, 0x8b, 0x39, 0x89, 0x1f, 0x2b, 0x8b, 0x36, 0x8a, 0x2f, 0x2c, 0x20, 0x8b, 0x34, 0x8a, 0x38, 0x23, 0x28, 0x8b, 0x3d, 0x89, 0x1c, 0x28, 0x8b, 0x3b, 0x8a, 0x38, 0x23, 0x28, 0x8b, 0x34, 0x8a, 0x33, 0x17, 0x23, 0x8b, 0x3b, 0x89, 0x36, 0x2d, 0x23, 0x8b, 0x33, 0x8a, 0x31, 0x1e, 0x2a, 0x8b, 0x33, 0x89, 0x1f, 0x2b, 0x8c, 0x2f, 0x89, 0x34, 0x20, 0x2c, 0x8b, 0x34, 0x8a, 0x38, 0x28, 0x1c, 0x8b, 0x3b, 0x89, 0x40, 0x23, 0x17, 0x8b, 0x3d, 0x8a, 0x3b, 0x14, 0x20, 0x8b, 0x38, 0x8a, 0x31, 0x15, 0x21, 0x8b, 0x39, 0x89, 0x28, 0x25, 0x2d, 0x8b, 0x36, 0x8a, 0x30, 0x1e, 0x2a, 0x8b, 0x39, 0x8a, 0x2b, 0x1f, 0x8b, 0x36, 0x89, 0x2f, 0x2c, 0x20, 0x8b, 0x34, 0x8a, 0x38, 0x28, 0x2c, 0x8b, 0x3d, 0x8a, 0x28, 0x1c, 0x8b, 0x3b, 0x89, 0x38, 0x28, 0x2c, 0x8b, 0x34, 0x8a, 0x36, 0x19, 0x25, 0x8b, 0x38, 0x8a, 0x36, 0x28, 0x2e, 0x8b, 0x34, 0x89, 0x33, 0x12, 0x1e, 0x8b, 0x34, 0x8a, 0x2a, 0x2e, 0x28, 0x8b, 0x31, 0x89, 0x2f, 0x27, 0x2a, 0x81, 0x23, 0x94, 0x32, 0x38, 0x1d, 0x8b, 0x33, 0x36, 0x1e, 0x8a, 0x33, 0x3b, 0x17, 0x95, 0x2f, 0x32, 0x20, 0x94, 0x31, 0x15, 0x21, 0x8b, 0x39, 0x8a, 0x2d, 0x28, 0x25, 0x8b, 0x36, 0x8a, 0x30, 0x1e, 0x2a, 0x8b, 0x39, 0x8a, 0x1f, 0x2b, 0x8b, 0x36, 0x89, 0x20, 0x2c, 0x8b, 0x2f, 0x8a, 0x34, 0x23, 0x2c, 0x8b, 0x38, 0x8a, 0x3d, 0x28, 0x1c, 0x8b, 0x3b, 0x8a, 0x38, 0x2c, 0x28, 0x8b, 0x34, 0x89, 0x33, 0x17, 0x23, 0x8b, 0x3b, 0x8a, 0x36, 0x23, 0x2d, 0x8b, 0x33, 0x8a, 0x31, 0x1e, 0x2a, 0x8b, 0x33, 0x8a, 0x2b, 0x1f, 0x8b, 0x2f, 0x89, 0x2c, 0x20, 0x8b, 0x34, 0x8a, 0x38, 0x28, 0x1c, 0x8b, 0x3b, 0x8a, 0x38, 0x40, 0x17, 0x8b, 0x3d, 0x8a, 0x32, 0x3b, 0x20, 0x8b, 0x38, 0x89, 0x31, 0x15, 0x21, 0x8b, 0x39, 0x8a, 0x25, 0x19, 0x8b, 0x36, 0x8a, 0x30, 0x2a, 0x1e, 0x8b, 0x39, 0x8a, 0x21, 0x2d, 0x8b, 0x36, 0x89, 0x2c, 0x20, 0x8b, 0x2f, 0x8a, 0x34, 0x28, 0x1c, 0x8b, 0x38, 0x89, 0x3d, 0x23, 0x17, 0x8b, 0x3b, 0x8a, 0x38, 0x28, 0x1c, 0x8b, 0x2f, 0x89, 0x2e, 0x19, 0x25, 0x8b, 0x31, 0x34, 0x8a, 0x12, 0x1e, 0x95, 0x2d, 0x0b, 0x17, 0x8b, 0x33, 0x36, 0x95, 0x34, 0x2c, 0x8a, 0x1c, 0x10, 0x96, 0x38, 0x1c, 0x28, 0x8b, 0x34, 0x89, 0x36, 0x23, 0x17, 0x8b, 0x38, 0x8b, 0x2f, 0x14, 0x20, 0x8b, 0x30, 0x89, 0x31, 0x21, 0x15, 0x8b, 0x39, 0x8a, 0x28, 0x25, 0x2d, 0x8b, 0x36, 0x89, 0x30, 0x2a, 0x1e, 0x8b, 0x39, 0x8a, 0x1f, 0x2b, 0x8b, 0x36, 0x8a, 0x2f, 0x2c, 0x20, 0x8b, 0x34, 0x89, 0x38, 0x23, 0x28, 0x8b, 0x3d, 0x8a, 0x1c, 0x28, 0x8b, 0x3b, 0x8a, 0x38, 0x23, 0x28, 0x8b, 0x34, 0x89, 0x33, 0x17, 0x23, 0x8b, 0x3b, 0x8a, 0x36, 0x2d, 0x27, 0x8b, 0x33, 0x8a, 0x31, 0x2a, 0x1e, 0x8b, 0x33, 0x89, 0x2b, 0x1f, 0x8b, 0x2f, 0x8a, 0x34, 0x20, 0x2c, 0x8b, 0x34, 0x8a, 0x38, 0x28, 0x1c, 0x8b, 0x3b, 0x8a, 0x40, 0x17, 0x23, 0x8b, 0x3d, 0x89, 0x3b, 0x20, 0x14, 0x8c, 0x38, 0x89, 0x31, 0x15, 0x21, 0x8b, 0x39, 0x8a, 0x2d, 0x25, 0x28, 0x8b, 0x36, 0x8a, 0x30, 0x1e, 0x2a, 0x8b, 0x39, 0x8a, 0x2b, 0x1f, 0x8b, 0x36, 0x8a, 0x2f, 0x2c, 0x20, 0x8b, 0x34, 0x8a, 0x38, 0x23, 0x28, 0x8b, 0x3d, 0x8a, 0x28, 0x1c, 0x8b, 0x3b, 0x89, 0x38, 0x23, 0x28, 0x8c, 0x34, 0x89, 0x36, 0x19, 0x25, 0x8b, 0x38, 0x8a, 0x36, 0x28, 0x2e, 0x8b, 0x34, 0x89, 0x33, 0x12, 0x1e, 0x8c, 0x34, 0x89, 0x2e, 0x28, 0x2a, 0x8c, 0x31, 0x89, 0x2f, 0x2a, 0x27, 0x81, 0x23, 0x94, 0x32, 0x38, 0x1d, 0x8c, 0x33, 0x36, 0x1e, 0x89, 0x3b, 0x33, 0x17, 0x95, 0x2f, 0x32, 0x20, 0x95, 0x31, 0x21, 0x15, 0x8b, 0x39, 0x8a, 0x2d, 0x28, 0x25, 0x8b, 0x36, 0x8a, 0x30, 0x2a, 0x1e, 0x8b, 0x39, 0x8a, 0x1f, 0x2b, 0x8b, 0x36, 0x8a, 0x2c, 0x20, 0x8b, 0x2f, 0x89, 0x34, 0x23, 0x28, 0x8c, 0x38, 0x89, 0x3d, 0x28, 0x1c, 0x8b, 0x3b, 0x8a, 0x38, 0x28, 0x23, 0x8b, 0x34, 0x8a, 0x33, 0x17, 0x23, 0x8b, 0x3b, 0x8a, 0x36, 0x2d, 0x27, 0x8b, 0x33, 0x8a, 0x31, 0x2a, 0x1e, 0x8b, 0x33, 0x8a, 0x2b, 0x1f, 0x8b, 0x2f, 0x89, 0x2c, 0x20, 0x8c, 0x34, 0x89, 0x38, 0x1c, 0x28, 0x8b, 0x3b, 0x8a, 0x40, 0x38, 0x23, 0x8b, 0x3d, 0x8a, 0x32, 0x3b, 0x14, 0x8b, 0x38, 0x8a, 0x31, 0x15, 0x21, 0x8b, 0x39, 0x8a, 0x19, 0x25, 0x8b, 0x36, 0x8a, 0x30, 0x2a, 0x1e, 0x8b, 0x39, 0x8a, 0x2d, 0x21, 0x8b, 0x36, 0x8a, 0x2c, 0x20, 0x8b, 0x2f, 0x89, 0x34, 0x1c, 0x28, 0x8b, 0x38, 0x8a, 0x3d, 0x23, 0x17, 0x8b, 0x3b, 0x89, 0x38, 0x1c, 0x28, 0x8c, 0x2f, 0x89, 0x2e, 0x19, 0x25, 0x8b, 0x31, 0x34, 0x8a, 0x12, 0x1e, 0x95, 0x2d, 0x0b, 0x17, 0x8c, 0x33, 0x36, 0x95, 0x2c, 0x34, 0x8a, 0x1c, 0x10, 0x95, 0x17, 0x96, 0x10, 0x8b, 0x3b, 0x2f, 0x8a, 0x31, 0x3d, 0x8b, 0x3e, 0x32, 0x8a, 0x3f, 0x33, 0x39, 0x94, 0x3b, 0x2f, 0x23, 0x8b, 0x39, 0x3d, 0x31, 0x8a, 0x23, 0x17, 0x95, 0x2d, 0x23, 0x27, 0x95, 0x3f, 0x39, 0x33, 0x94, 0x3b, 0x2f, 0x2d, 0x8b, 0x3d, 0x39, 0x31, 0x8a, 0x12, 0x1e, 0x8b, 0x3b, 0x2f, 0x17, 0x8a, 0x31, 0x3d, 0x22, 0x8b, 0x3f, 0x33, 0x15, 0x8a, 0x38, 0x40, 0x34, 0x95, 0x38, 0x3b, 0x2f, 0x8b, 0x31, 0x38, 0x3d, 0x89, 0x1c, 0x28, 0x95, 0x28, 0x2c, 0x23, 0x95, 0x34, 0x40, 0x38, 0x95, 0x38, 0x2f, 0x3b, 0x8b, 0x31, 0x3d, 0x38, 0x89, 0x28, 0x1c, 0x95, 0x29, 0x1d, 0x95, 0x1e, 0x2a, 0x95, 0x3d, 0x27, 0x23, 0x8b, 0x39, 0x3b, 0x33, 0x89, 0x23, 0x17, 0x95, 0x2d, 0x27, 0x23, 0x95, 0x2a, 0x1e, 0x95, 0x3d, 0x23, 0x27, 0x8b, 0x33, 0x3b, 0x39, 0x89, 0x23, 0x17, 0x95, 0x27, 0x23, 0x2d, 0x95, 0x1c, 0x28, 0x95, 0x3d, 0x28, 0x2c, 0x8b, 0x34, 0x3b, 0x38, 0x89, 0x23, 0x17, 0x95, 0x28, 0x23, 0x2c, 0x95, 0x1c, 0x28, 0x95, 0x3d, 0x28, 0x23, 0x8b, 0x38, 0x34, 0x3b, 0x8a, 0x20, 0x2c, 0x8b, 0x2f, 0x3b, 0x89, 0x3d, 0x31, 0x1f, 0x8b, 0x32, 0x3e, 0x8a, 0x3f, 0x39, 0x33, 0x95, 0x3b, 0x2f, 0x27, 0x8b, 0x39, 0x31, 0x3d, 0x8a, 0x23, 0x17, 0x94, 0x27, 0x2d, 0x23, 0x95, 0x33, 0x39, 0x3f, 0x95, 0x3b, 0x2f, 0x27, 0x8b, 0x3d, 0x31, 0x39, 0x8a, 0x12, 0x1e, 0x8b, 0x3b, 0x2f, 0x23, 0x89, 0x3d, 0x31, 0x22, 0x8b, 0x33, 0x3f, 0x15, 0x8a, 0x34, 0x40, 0x38, 0x95, 0x3b, 0x38, 0x2f, 0x8b, 0x3d, 0x31, 0x38, 0x8a, 0x1c, 0x28, 0x95, 0x28, 0x23, 0x2c, 0x95, 0x20, 0x2c, 0x8c, 0x34, 0x8a, 0x38, 0x28, 0x1c, 0x8b, 0x3b, 0x8a, 0x40, 0x38, 0x23, 0x8b, 0x3d, 0x8a, 0x32, 0x3b, 0x20, 0x8b, 0x38, 0x8a, 0x31, 0x15, 0x21, 0x8b, 0x39, 0x8a, 0x19, 0x25, 0x8b, 0x36, 0x8a, 0x30, 0x1e, 0x2a, 0x8b, 0x39, 0x8a, 0x2d, 0x21, 0x8b, 0x36, 0x8a, 0x2c, 0x20, 0x8b, 0x2f, 0x8a, 0x34, 0x28, 0x1c, 0x8b, 0x38, 0x89, 0x3d, 0x17, 0x23, 0x8b, 0x3b, 0x8a, 0x38, 0x1c, 0x28, 0x8b, 0x2f, 0x8a, 0x2e, 0x19, 0x25, 0x8b, 0x34, 0x31, 0x89, 0x1e, 0x12, 0x95, 0x2d, 0x17, 0x0b, 0x8b, 0x36, 0x33, 0x95, 0x2c, 0x34, 0x8a, 0x10, 0x1c, 0x95, 0x17, 0x23, 0x96, 0x20, 0x2c, 0x8b, 0x2f, 0x3b, 0x89, 0x31, 0x3d, 0x2b, 0x8b, 0x32, 0x3e, 0x89, 0x39, 0x3f, 0x33, 0x95, 0x2f, 0x3b, 0x23, 0x8b, 0x39, 0x31, 0x3d, 0x8a, 0x23, 0x17, 0x95, 0x2d, 0x23, 0x27, 0x95, 0x3f, 0x39, 0x33, 0x95, 0x2f, 0x3b, 0x23, 0x8b, 0x31, 0x3d, 0x39, 0x89, 0x1e, 0x12, 0x8c, 0x2f, 0x3b, 0x23, 0x89, 0x31, 0x3d, 0x22, 0x8b, 0x3f, 0x33, 0x15, 0x89, 0x40, 0x38, 0x34, 0x95, 0x3b, 0x2f, 0x38, 0x8b, 0x3d, 0x31, 0x38, 0x8a, 0x1c, 0x28, 0x95, 0x23, 0x28, 0x2c, 0x95, 0x38, 0x34, 0x40, 0x95, 0x3b, 0x38, 0x2f, 0x8b, 0x31, 0x3d, 0x38, 0x89, 0x1c, 0x28, 0x95, 0x29, 0x1d, 0x95, 0x2a, 0x1e, 0x95, 0x3d, 0x27, 0x23, 0x8b, 0x39, 0x3b, 0x33, 0x89, 0x17, 0x23, 0x95, 0x2d, 0x27, 0x23, 0x95, 0x1e, 0x2a, 0x95, 0x3d, 0x27, 0x23, 0x8b, 0x33, 0x39, 0x3b, 0x8a, 0x23, 0x17, 0x94, 0x2d, 0x23, 0x27, 0x95, 0x1c, 0x28, 0x95, 0x3d, 0x2c, 0x28, 0x8b, 0x34, 0x3b, 0x38, 0x89, 0x17, 0x23, 0x95, 0x2c, 0x28, 0x23, 0x95, 0x1c, 0x28, 0x94, 0x3d, 0x23, 0x2c, 0x8b, 0x38, 0x34, 0x3b, 0x8a, 0x2c, 0x20, 0x8b, 0x2f, 0x3b, 0x89, 0x31, 0x3d, 0x1f, 0x8b, 0x32, 0x3e, 0x8a, 0x3f, 0x39, 0x33, 0x94, 0x3b, 0x2f, 0x2d, 0x8b, 0x31, 0x39, 0x3d, 0x8a, 0x23, 0x17, 0x95, 0x2d, 0x27, 0x23, 0x95, 0x39, 0x3f, 0x33, 0x95, 0x3b, 0x2f, 0x27, 0x8b, 0x31, 0x39, 0x3d, 0x89, 0x12, 0x1e, 0x8b, 0x3b, 0x2f, 0x17, 0x8a, 0x31, 0x3d, 0x22, 0x8b, 0x33, 0x3f, 0x15, 0x89, 0x34, 0x40, 0x38, 0x95, 0x3b, 0x38, 0x2f, 0x8b, 0x3d, 0x31, 0x38, 0x8a, 0x28, 0x1c, 0x95, 0x28, 0x23, 0x2c, 0x95, 0x20, 0x2c, 0x8b, 0x34, 0x89, 0x38, 0x1c, 0x28, 0x8b, 0x3b, 0x8a, 0x38, 0x40, 0x23, 0x8b, 0x3d, 0x8a, 0x3b, 0x32, 0x20, 0x8b, 0x38, 0x89, 0x31, 0x15, 0x21, 0x8b, 0x39, 0x8a, 0x19, 0x25, 0x8b, 0x36, 0x8a, 0x30, 0x1e, 0x2a, 0x8b, 0x39, 0x89, 0x2d, 0x21, 0x8b, 0x36, 0x8a, 0x20, 0x2c, 0x8b, 0x2f, 0x8a, 0x34, 0x28, 0x1c, 0x8a, 0x38, 0x8a, 0x3d, 0x23, 0x17, 0x8b, 0x3b, 0x8a, 0x38, 0x28, 0x1c, 0x8b, 0x2f, 0x89, 0x2e, 0x25, 0x19, 0x8c, 0x31, 0x34, 0x89, 0x1e, 0x12, 0x95, 0x2d, 0x17, 0x0b, 0x8c, 0x33, 0x36, 0x95, 0x34, 0x2c, 0x8a, 0x1c, 0x10, 0x95, 0x17, 0x96, 0x40, 0x34, 0x3b, 0xff};